#include "mapview.h"
#include <QPixmap>
#include <QPainter>
#include "maploaddialog.h"
#include <QMessageBox>
#include "../external/transformable/transformable.h"
#include "../external/paramo/paramo.h"
#include <QDebug>

// 声明图层为全局变量
std::shared_ptr<MapView> map_view = nullptr;

MapView::MapView() : AsyncLayer(1)
{
    readMapList();
}

MapView::~MapView()
{
    // 由于map_view智能指针在局部静态对象之前析构，能够保证PARAMO调用有效
    saveMapList();

    // 释放地图内存
    for (qsizetype i = 0; i < map_list.size(); ++i)
    {
        if (map_list[i])
        {
            delete map_list[i];
            map_list[i] = nullptr;
        }
    }
}

void MapView::load()
{
    MapLoadDialog dialog;
    if (dialog.exec() == QDialog::Accepted)
    {
        MapInfo* info = new MapInfo(dialog.name(), dialog.path(), dialog.base(), dialog.size(), dialog.visible());

        // 载入失败，弹出警告
        if (!info || !info->loaded)
        {
            QMessageBox::critical(nullptr, "错误", "无法载入地图。");

            if (info) {
                delete info;
            }
        }
        else {
            std::unique_lock<std::mutex> lock;
            map_list.append(info);
        }
    }
}

void MapView::draw(QPixmap &pixmap)
{
    QPainter painter(&pixmap);
    std::unique_lock<std::mutex> lock;

    // 遍历地图列表
    for (qsizetype i = 0; i < map_list.size(); ++i)
    {
        auto map = map_list[i];
        // 成功载入且可见
        if (map->loaded  &&
            map->pixmap  &&
            map->visible &&
            inBox(map->base, map->size))
        {
            // 获取目标大小和绘制位置
            double x, y, w, h;
            TRANS->mapToPixel(map->base.x(), map->base.y(), x, y);
            TRANS->mapLenInPixel(map->size.width(), w);
            TRANS->mapLenInPixel(map->size.height(), h);

            // 目标矩形框
            QRectF target(x, y - h, w, h);
            QRectF source(0, 0, map->pixmap->width(), map->pixmap->height());

            // 绘制地图（不锁定宽高比）
            painter.drawPixmap(target, *map->pixmap, source);
        }
    }
}

bool MapView::inBox(const QPointF &point, const QSizeF &size)
{
    double left, top, right, bottom;
    TRANS->pixelToMap(0, 0, left, top);
    TRANS->pixelToMap(TRANS->width(), TRANS->height(), right, bottom);

    if (point.x() > right || point.y() > top) return false;

    if (point.x() + size.width() < left ||
        point.y() + size.height() < bottom) return false;

    return true;
}

void MapView::saveMapList()
{
    // 删除既有分支
    int num;
    if (PARAMO->get("mapList.num", num))
    {
        PARAMO->erase("mapList");
    }

    // 插入新分支
    if (map_list.size() > 0)
    {
        // 插入地图数量
        PARAMO->put("mapList.num", map_list.size());

        for (qsizetype i = 0; i < map_list.size(); ++i)
        {
            auto map = map_list[i];
            PARAMO->put("mapList." + std::to_string(i) + ".name", map->name.toStdString());
            PARAMO->put("mapList." + std::to_string(i) + ".path", map->path.toStdString());
            PARAMO->put("mapList." + std::to_string(i) + ".x", map->base.x());
            PARAMO->put("mapList." + std::to_string(i) + ".y", map->base.y());
            PARAMO->put("mapList." + std::to_string(i) + ".width", map->size.width());
            PARAMO->put("mapList." + std::to_string(i) + ".height", map->size.height());
            PARAMO->put("mapList." + std::to_string(i) + ".visible", map->visible);
        }
    }
}

void MapView::readMapList()
{
    int num;
    // 获取地图数量
    if (PARAMO->get("mapList.num", num))
    {
        for (int i = 0; i < num; ++i)
        {
            bool flag = true;

            // 获取地图名称
            std::string name;
            if (!PARAMO->get("mapList." + std::to_string(i) + ".name", name)) flag = false;

            // 获取地图路径
            std::string path;
            if (!PARAMO->get("mapList." + std::to_string(i) + ".path", path)) flag = false;

            // 获取地图原点
            double x, y;
            if (!PARAMO->get("mapList." + std::to_string(i) + ".x", x)) flag = false;
            if (!PARAMO->get("mapList." + std::to_string(i) + ".y", y)) flag = false;

            // 获取地图尺寸
            double width, height;
            if (!PARAMO->get("mapList." + std::to_string(i) + ".width", width)) flag = false;
            if (!PARAMO->get("mapList." + std::to_string(i) + ".height", height)) flag = false;

            // 获取地图可见性
            bool visible;
            if (!PARAMO->get("mapList." + std::to_string(i) + ".visible", visible)) flag = false;

            // 参数获取成功
            if (flag)
            {
                // 创建
                MapInfo* info = new MapInfo(QString::fromStdString(name), QString::fromStdString(path), QPointF(x, y), QSizeF(width, height), visible);

                if (info && info->loaded)
                {
                    // 插入有效地图
                    std::unique_lock<std::mutex> lock;
                    map_list.append(info);
                }
            }
        }
    }
}
